/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "RunningEnvelope.h"

void RunningEnvelope::set_key_off()
{
	if ( !envelope )
		return;

	key_off = true;
	if ( !sustaining )
	{
		if ( envelope->is_sustain_active() )
			sustaining = true;
		else
			sustaining = false;
	}
}

void RunningEnvelope::set_position( int pos )
{
	if( !envelope )
		return;

	if( pos < envelope->get_point_position( 0 ) || pos > envelope->get_point_position( envelope->size() - 1 ) )
		return;

	int temp_point( 0 );
	while( pos < envelope->get_point_position( temp_point ) )
		++temp_point;

	next_point = temp_point;
	prev_point = next_point - 1;
}

int RunningEnvelope::evaluate()const
{
	if ( !envelope )
		return 0;

	int val1 = envelope->get_point_value( prev_point );
	int val2 = envelope->get_point_value( next_point );
	int pos1 = envelope->get_point_position( prev_point );
	int pos2 = envelope->get_point_position( next_point );

	return val1 + (val2 - val1)*(position - pos1)/(pos2 - pos1);
}

void RunningEnvelope::advance()
{
	if ( !envelope )
		return;

	++position;

	if( !sustaining && envelope->is_sustain_active() )
	{
		//prevent from going beyond the sustain point
		if( position > envelope->get_sustain_position() )
			position = envelope->get_sustain_position();
	}

	while( position >= envelope->get_point_position( next_point ) )
	{
		++next_point;
		++prev_point;

		//loop active
		if( !sustaining && envelope->is_loop_active() )
			if( next_point > envelope->get_loop_end_point() )
			{
				prev_point = envelope->get_loop_start_point();
				next_point = prev_point + 1;
				position = envelope->get_point_position( prev_point );
			}

		if ( next_point >= envelope->size() )
		{
			next_point = envelope->size()-1;
			prev_point = next_point - 1;
			--position;
			break;
		}
	}
}

